/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package lanchatprojectclient;

/**
 *
 * @author Troy
 */
import protocols.*;

import java.io.*;
import java.math.BigInteger;
import java.net.*;
import java.util.Random;
import java.util.Vector;
import javax.swing.*;


//Lớp chính
public class ChatHacker
{
	private boolean connected;

	int serverSocketNumber;
	String serverAddress;
        String infoClient;
	private Socket socket;

	String Name;
        String Pass;
        String offMsg,offMsgServer;
        public boolean check;
        public boolean check2,clchange;
        String Status,temp[];int i=0;
	private int clientID;

	ObjectOutputStream out;
	ObjectInputStream in;

	DefaultListModel clientList;

	private InputListener listener;
	HackerInterfaceDesign window;
        boolean testconnect;

        public BigInteger N,e,d;

	//Lắng nghe luồng thông điệp đến
	class InputListener extends Thread
	{
		//Cung cấp phương thức tạm dừng để lắng nghe
		boolean running = false;

		public void run()
		{
			//Vòng lặp vô tận nhưng nếu nghe tạm dừng thỉ bỏ qua code
			while( true )
			{
				if( running )
				{
					//Nhận diện thông điệp và đưa ra hành động xử lý phù hợp
					try
					{
						Object serverMsg = in.readObject();

						if( serverMsg instanceof Message )
						{
							window.showMessage( (Message)serverMsg ); 
						}
                                                else if( serverMsg instanceof MessageRSA )
                                                {
                                                        window.showMessageRSA( (MessageRSA)serverMsg );
                                                }
						else if( serverMsg instanceof ChatRequest )
						{
							window.openNewTab( ((ChatRequest)serverMsg).senderId );
						}
						else if( serverMsg instanceof UpdateList )
						{
							//Nếu người sử dụng đăng nhập
							if( ((UpdateList)serverMsg).re == 1 )
							{                                                                   

                                                             clientList.addElement( "<<on>> "+((UpdateList)serverMsg).newClient );
                                                             for (int i=0;i<clientList.getSize();i++)
                                                             {String[] str = clientList.get(i).toString().split(" ''");
                                                                if(str[0].equalsIgnoreCase("<<off>> "+((UpdateList)serverMsg).newClient))
                                                                {
                                                                    window.notifyUserLeft(clientList.get(i).toString());
                                                                    clientList.removeElementAt(i);
                                                                    clientList.add(i, ((UpdateList)serverMsg).newClient+" đã đăng nhập lại");
                                                                }
                                                            }
							}
                                                        //Nếu người sử dụng thay đổi trạng thái
                                                        else if( ((UpdateList)serverMsg).re == 3 ){
                                                            for (int i=0;i<clientList.getSize();i++)
                                                            {String[] str = clientList.get(i).toString().split(" ''");
                                                                if(str[0].equalsIgnoreCase("<<on>> "+((UpdateList)serverMsg).newClient))
                                                                {
                                                                    clientList.removeElementAt(i);
                                                                    clientList.add(i, "<<on>> "+((UpdateList)serverMsg).newClient+" ''"+((UpdateList)serverMsg).newStatus+"''" );
                                                                }
                                                            }                                                            
                                                        }
							//Nếu người sử dụng đăng xuất
							else
							{   for (int i=0;i<clientList.getSize();i++)
                                                            {String[] str = clientList.get(i).toString().split(" ''");
                                                                if(str[0].equalsIgnoreCase("<<on>> "+((UpdateList)serverMsg).newClient))
                                                                {
                                                                    window.notifyUserLeft(clientList.get(i).toString());
                                                                    clientList.removeElementAt(i);
                                                                    clientList.add(i, "<<off>> "+((UpdateList)serverMsg).newClient);
                                                                }
                                                            }

                                                        }
						}
						else if( serverMsg instanceof ServerShutDown )
						{
							disconnectFromServer( false );
							//window.notifyDisconnect();
							JOptionPane.showMessageDialog( window,"Server Đã Tắt","Lỗi kết nối",JOptionPane.ERROR_MESSAGE );
						}
                                                //Kiểm tra đăng kí
                                                else if(serverMsg instanceof Report)
                                                {
                                                    check = ((Report)serverMsg).success;
                                                    if(check==false)
                                                    JOptionPane.showMessageDialog( window,"Tài khoản đã tồn tại!!!","Lỗi tài khoản",JOptionPane.ERROR_MESSAGE );
                                                    else JOptionPane.showMessageDialog(window, "Đăng ký thành công!!!","Thành công",JOptionPane.INFORMATION_MESSAGE);
                                                }
                                                //Nhận tin offline từ server và gửi đi
                                                else if(serverMsg instanceof OfflineMessage)
                                                {
                                                    offMsgServer = ((OfflineMessage)serverMsg).offmsg;
                                                    window.sendOfflineMessage(offMsgServer);
                                                }
                                                else if(serverMsg instanceof key)
                                                {
                                                    String getkey = ((key)serverMsg).keyRSA;
                                                    System.out.println("Getkey:"+getkey);
                                                    String temp[] = getkey.split(":");
                                                    N = new BigInteger(temp[0]);
                                                    e = new BigInteger(temp[1]);
                                                    
                                                }
					}
					catch( ClassNotFoundException cnfe )
					{
						JOptionPane.showMessageDialog( window, "Không tìm thấy lớp.", "Lỗi", JOptionPane.ERROR_MESSAGE );
						shutDown();
					}
					catch( InvalidClassException ice )
					{
						JOptionPane.showMessageDialog( window, "Lớp bị sai.", "Lỗi", JOptionPane.ERROR_MESSAGE );
						shutDown();
					}
					catch( StreamCorruptedException sce )
					{
						JOptionPane.showMessageDialog( window, "Kiểm soát thông tin trong luồng không phù hợp.", "Lỗi", JOptionPane.ERROR_MESSAGE );
						shutDown();
					}
					catch( OptionalDataException ode )
					{
						JOptionPane.showMessageDialog( window, "Dữ liệu nguyên thủy đã được tìm thấy ở luồng thay vì đối tượng.", "Lỗi", JOptionPane.ERROR_MESSAGE );
						shutDown();
					}
					catch( IOException ioe)
					{						
					}
				}
			}
		}
	}

	//Gửi tin nhắn cho cả room
	void sendPublicMessage( String userMsg ) throws IOException
	{
		Message msg = new Message();
		msg.audience = true;
		msg.roomNumber = 0;
		msg.senderId = clientID;
		msg.message = Name + " nói >>> " + userMsg;
		out.writeObject( msg );
		out.flush();
	}

	//Gửi tin nhắn riêng tư với người dùng khác
	void sendPrivateMessage( int recipient, String userMsg ) throws IOException
	{
		Message msg = new Message();
		msg.audience = false;
		msg.recieverId = recipient;
		msg.senderId = clientID;
		msg.message = Name + " nói >>> " + userMsg;
		out.writeObject( msg );
		out.flush();
	}

       
        //Gửi trạng thái người dùng nhập
        void sendStt(String str) throws IOException
        {
            Status st = new Status();
            st.stt = str;
            out.writeObject(st);
            out.flush();
        }

        //Gửi tin offline
        void sendOfflineMessage(String str) throws IOException
        {
            OfflineMessage om = new OfflineMessage();
            om.offmsg = str;
            out.writeObject(om);
            out.flush();
        }
        //Gửi yêu cầu tin offline
        void sendRequestOffMsg(String str) throws IOException
        {
            requestOffMsg rom = new requestOffMsg();
            rom.request = str;
            out.writeObject(rom);
            out.flush();
        }

	//Gửi yêu cầu chat riêng tư với người dùng nào đó
	void sendChatRequest( int recieverId )
	{
		ChatRequest request = new ChatRequest();
		request.recieverId = recieverId;
		request.senderId = clientID;

		try
		{
			out.writeObject( request );
		}
		catch( IOException io_e )
		{}
	}

        //Gửi yêu cầu đăng xuất
        void sendLogout(boolean boo) throws IOException
        {
            ReportLogin rl= new ReportLogin();
            rl.success = boo;
            out.writeObject(rl);
            out.flush();
        }

        //Gửi yêu cầu đăng ký
        void setLogon( String newID, String newPass )
	{
		try
		{			
                        LogOn log = new LogOn();
                        log.infomation = newID + ";" + newPass;                        
                        out.writeObject(log);
                        out.flush();

		}
		catch( IOException io_e )
		{

		}
	}

	//Lưu giá trị định dạng vào file
	void setConfiguration( String newServer, int newPort )
	{
		try
		{
			FileWriter configFile = new FileWriter("clientConfig.cfg");
			configFile.write( newServer.trim() + ";" + newPort + ";" );
			configFile.close();
		}
		catch( IOException io_e )
		{
			JOptionPane.showMessageDialog( window,"Không thể lưu lại","Lỗi tập tin",JOptionPane.ERROR_MESSAGE );
		}
	}

	//Lấy giá trị định dạng từ file
	void getConfiguration()
	{
		try
		{
			char[] buffer = new char[255];

			FileReader configFile = new FileReader("clientConfig.cfg");

			configFile.read( buffer );
			serverAddress = String.copyValueOf( buffer );
			String[] temp = serverAddress.split(";");

			serverAddress = temp[0];
			serverSocketNumber = Integer.parseInt( temp[1] );

		}
		catch( FileNotFoundException fnf_e )
		{
			JOptionPane.showMessageDialog( window,"Không tìm thấy tập tin","Lỗi tìm kiếm tập tin",JOptionPane.ERROR_MESSAGE );

			serverSocketNumber = 1809;
			serverAddress = "localhost";
		}
		catch( IOException io_e )
		{
			JOptionPane.showMessageDialog( window,"Có lỗi khi đọc tập tin định dạng, dùng mặc định?","Lỗi định dạng",JOptionPane.ERROR_MESSAGE );

			serverSocketNumber = 1809;
			serverAddress = "localhost";
		}
	}

	//Thực hiện các bước ngắt kết nối
	//reason = true nghĩa là người dùng chọn
	//reason = false nghĩa là do server
	synchronized void disconnectFromServer( boolean reason )
	{
		try
		{
			if( connected )
			{
				//Dừng công cụ lắng nghe thread
				listener.running = false;

				if( reason = true )
				{
					out.writeObject( new LogOut() );
					out.flush();
				}

				out.close();
				socket.close();

				clientList.clear();
				connected = false;
			}
		}
		catch( IOException ex )
		{}
	}

	//Thực hiện từng bước kết nối
	synchronized boolean connectToServer()
	{
		getConfiguration();

		try
		{
			InetAddress addr = InetAddress.getByName( serverAddress );
			socket = new Socket( addr,serverSocketNumber );
		}
		catch( UnknownHostException e )
		{
			JOptionPane.showMessageDialog( window,"Không tìm thấy host, định dạng lại...","Lỗi host",JOptionPane.ERROR_MESSAGE );
			return false;
		}
		catch( IOException e )
		{
			JOptionPane.showMessageDialog( window,"Không tìm thấy server, kiểm tra lại nếu server thực sự tồn tại...","Lỗi socket",JOptionPane.ERROR_MESSAGE );
			return false;
		}

		try
		{
			in = new ObjectInputStream( socket.getInputStream() );
			out = new ObjectOutputStream( socket.getOutputStream() );
		}
		catch( IOException e )
		{
			JOptionPane.showMessageDialog( window,"Không thể tạo luồng dữ liệu, đóng client...","Lỗi luồng dữ liệu",JOptionPane.ERROR_MESSAGE );
			try
			{
				socket.close();
			}
			catch( IOException io_e )
			{}

			return false;
		}


		if( !handShake() )
			return false;

		listener.running = true;

		//Nếu kết nối lần đầu thì khởi động đối tượng nghe
		if( listener.isAlive() == false )
		{
			listener.start();
		}

		connected = true;
                testconnect = true;
		return true;
	}

	//Thiết lập các thông số với server
	private boolean handShake()

	{

		try
		{

                        if(((ConnectionNotice) in.readObject()).status)
			{
				out.writeObject( Name + ";"+Pass );
				if( ((ConnectionNotice)in.readObject()).status == false )
				{
					JOptionPane.showMessageDialog( window,"Tài khoản hay mật khẩu chưa đúng hoặc đang được sử dụng, vui lòng thử lại hoặc đăng ký mới!!!\nLưu ý: dùng tài khoản test, mật khẩu test để đăng ký!","Lỗi đăng nhập",JOptionPane.ERROR_MESSAGE );
					return false;
				}

				clientList = (DefaultListModel)in.readObject();
				clientID = clientList.getSize()-1;
				return true;
			}
                        else if(((ConnectionNotice) in.readObject()).status2)
			{
				out.writeObject( Name + ";"+Pass );
				if( ((ConnectionNotice)in.readObject()).status2 == false )
				{
					JOptionPane.showMessageDialog( window,"Tài khoản đang sử dụng, vui lòng thử lại hoặc đăng ký mới!!!\nLưu ý: dùng tài khoản test, mật khẩu test để đăng ký!","Lỗi đăng nhập",JOptionPane.ERROR_MESSAGE );
					return false;
				}

				clientList = (DefaultListModel)in.readObject();
				clientID = clientList.getSize()-1;
				return true;
			}
                       
			else
			{
				JOptionPane.showMessageDialog( window, "Quá giới hạn máy khách server cho phép", "Hạn chế kết nối", JOptionPane.ERROR_MESSAGE );
			}
		}
		catch( Exception e )
		{}

		return false;
	}

	void shutDown()
	{
		disconnectFromServer( true );
		listener = null;
		System.exit(0);
	}

	ChatHacker()
	{
		connected = false;
		listener = new InputListener();
		window = new HackerInterfaceDesign( this );
                window.setVisible(true);
	}

	public static void main( String args[] )  throws IOException
	{
            new ChatHacker();
	}
}


